package br.com.foxinline.servico;

import br.com.foxinline.generico.ServicoGenerico;
import br.com.foxinline.modelo.Bairro;
import br.com.foxinline.modelo.Cidade;
import br.com.foxinline.modelo.Coordenada;
import br.com.foxinline.modelo.GrupoBairro;
import br.com.foxinline.util.GrupoUtilitario;
import java.beans.Transient;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.persistence.Query;

/**
 *
 * @author laverson
 */
@Stateless
@DeclareRoles(GrupoUtilitario.ADMINISTRADOR)
public class BairroServico extends ServicoGenerico<Bairro> {

    @EJB
    CidadeServico cidadeServico;
    @EJB
    UsuarioServico usuarioServico;
    private Long quantidadeRegistrosResults;

    public BairroServico() {
        super(Bairro.class);
    }

    @Override
    @RolesAllowed(GrupoUtilitario.ADMINISTRADOR)
    public void update(Bairro entity) {
        super.update(entity);
    }

    @Override
    public List<Bairro> findAll() {
        return getEntityManager().createQuery("select b from " + Bairro.class.getSimpleName() + " b join b.cidade c where b.ativo = true").getResultList();
    }

    public List<Bairro> autoComplete(String query) {
        return findByName(query);
    }

    public List<Bairro> autocomplete(String query, Cidade cidade) {
        return findByName(query, cidade);
    }

    public List<Bairro> findByName(String query) {
        List<Bairro> results = getEntityManager().createQuery("select e from " + Bairro.class.getSimpleName() + " e where lower(e.nome) like '%" + query.toLowerCase().trim().replace(" ", "%") + "%' and e.ativo = true").getResultList();
        return results;
    }

    public List<Bairro> findByName(String query, Cidade cidade) {
        String sql = "select b from " + Bairro.class.getSimpleName() + " b ";

        if (cidade != null && cidade.getNome() != null && !cidade.getNome().equals("")) {
            sql += " JOIN b.cidade c ";
        }

        sql += "where lower(b.nome) like lower(:nome)";

        if (cidade != null && cidade.getNome() != null && !cidade.getNome().equals("")) {
            sql += " and lower(c.nome) like lower(:nomeCidade)";
        }
            sql += " and b.ativo = true";

        Query querya = getEntityManager().createQuery(sql);

        if (cidade != null && cidade.getNome() != null && !cidade.getNome().equals("")) {
            querya.setParameter("nome", "%" + query.trim().replace(" ", "%") + "%");
        }

        if (cidade != null && cidade.getNome() != null && !cidade.getNome().equals("")) {
            querya.setParameter("nomeCidade", "%" + cidade.getNome().replace(" ", "%") + "%");
        }

        return querya.getResultList();
    }

    public List<Bairro> findCidade(Bairro bairro, Cidade cidade) {
        String sql = "select b from Bairro b ";

        if (cidade != null) {
            sql += " JOIN b.cidade c ";
        }

        sql += " WHERE ";

        if (bairro.getNome() != null && !bairro.getNome().equals("")) {
            sql += " lower(b.nome) like lower(:nome) and ";
        }

        if (cidade != null) {
            sql += " c.id = :cidade and ";
        }

        sql += " 1=1 Order by b.nome ASC";

        Query query = getEntityManager().createQuery(sql);

        if (cidade != null) {
            query.setParameter("cidade", cidade.getId());
        }

        if (bairro.getNome() != null && !bairro.getNome().equals("")) {
            query.setParameter("nome", "%" + bairro.getNome() + "%");
        }

        return query.getResultList();
    }

    public List<Coordenada> lstCoordenadaBairro(Bairro bairro) {
        String sql = "select c from Bairro b JOIN b.coordenadas c WHERE b.id = :id order by c.id";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("id", bairro.getId());


        return query.getResultList();
    }

    public List<Bairro> autocomplete(String name) {
        String sql = "Select b from Bairro b JOIN b.cidade c where lower(b.nome) like lower(:name) and c.id = 5658";

        Query query = getEntityManager().createQuery(sql).setMaxResults(50);

        if (name != null) {
            query.setParameter("name", "" + name + "%");
        }

        return query.getResultList();
    }

    public List<Bairro> autocomplete(String name, List<Bairro> bairros) {

        List<Long> bairrosId = null;

        if (bairros != null && !bairros.isEmpty()) {

            bairrosId = new ArrayList<Long>();

            for (Bairro bairro : bairros) {
                bairrosId.add(bairro.getId());
            }
        }

        String sql = "Select b from Bairro b JOIN b.cidade c where lower(b.nome) like lower(:name) and c.id = 5658 ";

        if (bairrosId != null) {
            sql += "AND b.id not in :bairrosId";
        }

        Query query = getEntityManager().createQuery(sql).setMaxResults(50);

        if (name != null) {
            query.setParameter("name", "%" + name + "%");
        }
        if (bairrosId != null) {
            query.setParameter("bairrosId", bairrosId);
        }

        return query.getResultList();
    }

    public List<Bairro> findGrupoBairro(GrupoBairro grupoBairro) {
        String sql = "SELECT bairro FROM " + GrupoBairro.class.getSimpleName()
                + " grupoBairro JOIN grupoBairro.bairros bairro "
                + "WHERE grupoBairro = :grupoBairro";
        Query query = getEntityManager().createQuery(sql);
        query.setParameter("grupoBairro", grupoBairro);
        return query.getResultList();
    }

    @Override
    public List<Bairro> find(Bairro entidade, Integer first, Integer pageSize) {
        String select = "select b ";
        String sql = "from Bairro b ";
        String orderBy = " order by b.nome ASC";

        Cidade cidade = entidade.getCidade() != null ? entidade.getCidade() : null;

        if (cidade != null) {
            sql += " JOIN b.cidade c ";
        }

        sql += " WHERE ";

        if (entidade.getNome() != null && !entidade.getNome().equals("")) {
            sql += " lower(b.nome) like lower(:nome) and ";
        }

        if (cidade != null) {
            sql += " c.id = :cidade and ";
        }

        sql += " b.ativo = true ";

        Query query = getEntityManager().createQuery(select.concat(sql).concat(orderBy));

        setQuantidadeRegistros(sql, cidade, entidade, query);

        setParameters(cidade, entidade, query);

        if (first != null && pageSize != null) {
            query.setFirstResult(first).setMaxResults(pageSize);
        }

        return query.getResultList();
    }

    @Transient
    private void setParameters(Cidade cidade, Bairro entidade, Query query) {
        if (cidade != null) {
            query.setParameter("cidade", cidade.getId());
        }

        if (entidade.getNome() != null && !entidade.getNome().equals("")) {
            query.setParameter("nome", "%" + entidade.getNome() + "%");
        }
    }

    private void setQuantidadeRegistros(String sql, Cidade cidade, Bairro entidade, Query query) {

        String select = "SELECT count(b) ";

        query = getEntityManager().createQuery(select + sql);

        setParameters(cidade, entidade, query);

        quantidadeRegistrosResults = (Long) query.getSingleResult();
    }

    @Override
    public Long quantidadeRegistros() {
        return quantidadeRegistrosResults;
    }
}
